/// This map is derived off of what coreutils uses in printing errors. This is
/// equivalent to `strerror`, but as strings with constant lifetime.
pub const coreutils_error_map = brk: {
    // macOS and Linux have slightly different error messages.
    const entries: []const struct { [:0]const u8, [:0]const u8 } = switch (Environment.os) {
        // Since windows is just an emulation of linux, it will derive the linux error messages.
        .linux, .windows, .wasm => &.{
            .{ "EPERM", "Operation not permitted" },
            .{ "ENOENT", "No such file or directory" },
            .{ "ESRCH", "No such process" },
            .{ "EINTR", "Interrupted system call" },
            .{ "EIO", "Input/output error" },
            .{ "ENXIO", "No such device or address" },
            .{ "E2BIG", "Argument list too long" },
            .{ "ENOEXEC", "Exec format error" },
            .{ "EBADF", "Bad file descriptor" },
            .{ "ECHILD", "No child processes" },
            .{ "EAGAIN", "Resource temporarily unavailable" },
            .{ "ENOMEM", "Cannot allocate memory" },
            .{ "EACCES", "Permission denied" },
            .{ "EFAULT", "Bad address" },
            .{ "ENOTBLK", "Block device required" },
            .{ "EBUSY", "Device or resource busy" },
            .{ "EEXIST", "File exists" },
            .{ "EXDEV", "Invalid cross-device link" },
            .{ "ENODEV", "No such device" },
            .{ "ENOTDIR", "Not a directory" },
            .{ "EISDIR", "Is a directory" },
            .{ "EINVAL", "Invalid argument" },
            .{ "ENFILE", "Too many open files in system" },
            .{ "EMFILE", "Too many open files" },
            .{ "ENOTTY", "Inappropriate ioctl for device" },
            .{ "ETXTBSY", "Text file busy" },
            .{ "EFBIG", "File too large" },
            .{ "ENOSPC", "No space left on device" },
            .{ "ESPIPE", "Illegal seek" },
            .{ "EROFS", "Read-only file system" },
            .{ "EMLINK", "Too many links" },
            .{ "EPIPE", "Broken pipe" },
            .{ "EDOM", "Numerical argument out of domain" },
            .{ "ERANGE", "Numerical result out of range" },
            .{ "EDEADLK", "Resource deadlock avoided" },
            .{ "ENAMETOOLONG", "File name too long" },
            .{ "ENOLCK", "No locks available" },
            .{ "ENOSYS", "Function not implemented" },
            .{ "ENOTEMPTY", "Directory not empty" },
            .{ "ELOOP", "Too many levels of symbolic links" },
            .{ "ENOMSG", "No message of desired type" },
            .{ "EIDRM", "Identifier removed" },
            .{ "ECHRNG", "Channel number out of range" },
            .{ "EL2NSYNC", "Level 2 not synchronized" },
            .{ "EL3HLT", "Level 3 halted" },
            .{ "EL3RST", "Level 3 reset" },
            .{ "ELNRNG", "Link number out of range" },
            .{ "EUNATCH", "Protocol driver not attached" },
            .{ "ENOCSI", "No CSI structure available" },
            .{ "EL2HLT", "Level 2 halted" },
            .{ "EBADE", "Invalid exchange" },
            .{ "EBADR", "Invalid request descriptor" },
            .{ "EXFULL", "Exchange full" },
            .{ "ENOANO", "No anode" },
            .{ "EBADRQC", "Invalid request code" },
            .{ "EBADSLT", "Invalid slot" },
            .{ "EBFONT", "Bad font file format" },
            .{ "ENOSTR", "Device not a stream" },
            .{ "ENODATA", "No data available" },
            .{ "ETIME", "Timer expired" },
            .{ "ENOSR", "Out of streams resources" },
            .{ "ENONET", "Machine is not on the network" },
            .{ "ENOPKG", "Package not installed" },
            .{ "EREMOTE", "Object is remote" },
            .{ "ENOLINK", "Link has been severed" },
            .{ "EADV", "Advertise error" },
            .{ "ESRMNT", "Srmount error" },
            .{ "ECOMM", "Communication error on send" },
            .{ "EPROTO", "Protocol error" },
            .{ "EMULTIHOP", "Multihop attempted" },
            .{ "EDOTDOT", "RFS specific error" },
            .{ "EBADMSG", "Bad message" },
            .{ "EOVERFLOW", "Value too large for defined data type" },
            .{ "ENOTUNIQ", "Name not unique on network" },
            .{ "EBADFD", "File descriptor in bad state" },
            .{ "EREMCHG", "Remote address changed" },
            .{ "ELIBACC", "Can not access a needed shared library" },
            .{ "ELIBBAD", "Accessing a corrupted shared library" },
            .{ "ELIBSCN", ".lib section in a.out corrupted" },
            .{ "ELIBMAX", "Attempting to link in too many shared libraries" },
            .{ "ELIBEXEC", "Cannot exec a shared library directly" },
            .{ "EILSEQ", "Invalid or incomplete multibyte or wide character" },
            .{ "ERESTART", "Interrupted system call should be restarted" },
            .{ "ESTRPIPE", "Streams pipe error" },
            .{ "EUSERS", "Too many users" },
            .{ "ENOTSOCK", "Socket operation on non-socket" },
            .{ "EDESTADDRREQ", "Destination address required" },
            .{ "EMSGSIZE", "Message too long" },
            .{ "EPROTOTYPE", "Protocol wrong type for socket" },
            .{ "ENOPROTOOPT", "Protocol not available" },
            .{ "EPROTONOSUPPORT", "Protocol not supported" },
            .{ "ESOCKTNOSUPPORT", "Socket type not supported" },
            .{ "EOPNOTSUPP", "Operation not supported" },
            .{ "EPFNOSUPPORT", "Protocol family not supported" },
            .{ "EAFNOSUPPORT", "Address family not supported by protocol" },
            .{ "EADDRINUSE", "Address already in use" },
            .{ "EADDRNOTAVAIL", "Cannot assign requested address" },
            .{ "ENETDOWN", "Network is down" },
            .{ "ENETUNREACH", "Network is unreachable" },
            .{ "ENETRESET", "Network dropped connection on reset" },
            .{ "ECONNABORTED", "Software caused connection abort" },
            .{ "ECONNRESET", "Connection reset by peer" },
            .{ "ENOBUFS", "No buffer space available" },
            .{ "EISCONN", "Transport endpoint is already connected" },
            .{ "ENOTCONN", "Transport endpoint is not connected" },
            .{ "ESHUTDOWN", "Cannot send after transport endpoint shutdown" },
            .{ "ETOOMANYREFS", "Too many references: cannot splice" },
            .{ "ETIMEDOUT", "Connection timed out" },
            .{ "ECONNREFUSED", "Connection refused" },
            .{ "EHOSTDOWN", "Host is down" },
            .{ "EHOSTUNREACH", "No route to host" },
            .{ "EALREADY", "Operation already in progress" },
            .{ "EINPROGRESS", "Operation now in progress" },
            .{ "ESTALE", "Stale file handle" },
            .{ "EUCLEAN", "Structure needs cleaning" },
            .{ "ENOTNAM", "Not a XENIX named type file" },
            .{ "ENAVAIL", "No XENIX semaphores available" },
            .{ "EISNAM", "Is a named type file" },
            .{ "EREMOTEIO", "Remote I/O error" },
            .{ "EDQUOT", "Disk quota exceeded" },
            .{ "ENOMEDIUM", "No medium found" },
            .{ "EMEDIUMTYPE", "Wrong medium type" },
            .{ "ECANCELED", "Operation canceled" },
            .{ "ENOKEY", "Required key not available" },
            .{ "EKEYEXPIRED", "Key has expired" },
            .{ "EKEYREVOKED", "Key has been revoked" },
            .{ "EKEYREJECTED", "Key was rejected by service" },
            .{ "EOWNERDEAD", "Owner died" },
            .{ "ENOTRECOVERABLE", "State not recoverable" },
            .{ "ERFKILL", "Operation not possible due to RF-kill" },
            .{ "EHWPOISON", "Memory page has hardware error" },
        },
        // Mac has slightly different messages. To keep it consistent with bash/coreutils,
        // it will use those altered messages.
        .mac => &.{
            .{ "E2BIG", "Argument list too long" },
            .{ "EACCES", "Permission denied" },
            .{ "EADDRINUSE", "Address already in use" },
            .{ "EADDRNOTAVAIL", "Can't assign requested address" },
            .{ "EAFNOSUPPORT", "Address family not supported by protocol family" },
            .{ "EAGAIN", "non-blocking and interrupt i/o. Resource temporarily unavailable" },
            .{ "EALREADY", "Operation already in progress" },
            .{ "EAUTH", "Authentication error" },
            .{ "EBADARCH", "Bad CPU type in executable" },
            .{ "EBADEXEC", "Program loading errors. Bad executable" },
            .{ "EBADF", "Bad file descriptor" },
            .{ "EBADMACHO", "Malformed Macho file" },
            .{ "EBADMSG", "Bad message" },
            .{ "EBADRPC", "RPC struct is bad" },
            .{ "EBUSY", "Device / Resource busy" },
            .{ "ECANCELED", "Operation canceled" },
            .{ "ECHILD", "No child processes" },
            .{ "ECONNABORTED", "Software caused connection abort" },
            .{ "ECONNREFUSED", "Connection refused" },
            .{ "ECONNRESET", "Connection reset by peer" },
            .{ "EDEADLK", "Resource deadlock avoided" },
            .{ "EDESTADDRREQ", "Destination address required" },
            .{ "EDEVERR", "Device error, for example paper out" },
            .{ "EDOM", "math software. Numerical argument out of domain" },
            .{ "EDQUOT", "Disc quota exceeded" },
            .{ "EEXIST", "File or folder exists" },
            .{ "EFAULT", "Bad address" },
            .{ "EFBIG", "File too large" },
            .{ "EFTYPE", "Inappropriate file type or format" },
            .{ "EHOSTDOWN", "Host is down" },
            .{ "EHOSTUNREACH", "No route to host" },
            .{ "EIDRM", "Identifier removed" },
            .{ "EILSEQ", "Illegal byte sequence" },
            .{ "EINPROGRESS", "Operation now in progress" },
            .{ "EINTR", "Interrupted system call" },
            .{ "EINVAL", "Invalid argument" },
            .{ "EIO", "Input/output error" },
            .{ "EISCONN", "Socket is already connected" },
            .{ "EISDIR", "Is a directory" },
            .{ "ELOOP", "Too many levels of symbolic links" },
            .{ "EMFILE", "Too many open files" },
            .{ "EMLINK", "Too many links" },
            .{ "EMSGSIZE", "Message too long" },
            .{ "EMULTIHOP", "Reserved" },
            .{ "ENAMETOOLONG", "File name too long" },
            .{ "ENEEDAUTH", "Need authenticator" },
            .{ "ENETDOWN", "ipc/network software - operational errors Network is down" },
            .{ "ENETRESET", "Network dropped connection on reset" },
            .{ "ENETUNREACH", "Network is unreachable" },
            .{ "ENFILE", "Too many open files in system" },
            .{ "ENOATTR", "Attribute not found" },
            .{ "ENOBUFS", "No buffer space available" },
            .{ "ENODATA", "No message available on STREAM" },
            .{ "ENODEV", "Operation not supported by device" },
            .{ "ENOENT", "No such file or directory" },
            .{ "ENOEXEC", "Exec format error" },
            .{ "ENOLCK", "No locks available" },
            .{ "ENOLINK", "Reserved" },
            .{ "ENOMEM", "Out of memory" },
            .{ "ENOMSG", "No message of desired type" },
            .{ "ENOPOLICY", "No such policy registered" },
            .{ "ENOPROTOOPT", "Protocol not available" },
            .{ "ENOSPC", "No space left on device" },
            .{ "ENOSR", "No STREAM resources" },
            .{ "ENOSTR", "Not a STREAM" },
            .{ "ENOSYS", "Function not implemented" },
            .{ "ENOTBLK", "Block device required" },
            .{ "ENOTCONN", "Socket is not connected" },
            .{ "ENOTDIR", "Not a directory" },
            .{ "ENOTEMPTY", "Directory not empty" },
            .{ "ENOTRECOVERABLE", "State not recoverable" },
            .{ "ENOTSOCK", "ipc/network software - argument errors. Socket operation on non-socket" },
            .{ "ENOTSUP", "Operation not supported" },
            .{ "ENOTTY", "Inappropriate ioctl for device" },
            .{ "ENXIO", "Device not configured" },
            .{ "EOVERFLOW", "Value too large to be stored in data type" },
            .{ "EOWNERDEAD", "Previous owner died" },
            .{ "EPERM", "Operation not permitted" },
            .{ "EPFNOSUPPORT", "Protocol family not supported" },
            .{ "EPIPE", "Broken pipe" },
            .{ "EPROCLIM", "quotas & mush. Too many processes" },
            .{ "EPROCUNAVAIL", "Bad procedure for program" },
            .{ "EPROGMISMATCH", "Program version wrong" },
            .{ "EPROGUNAVAIL", "RPC prog. not avail" },
            .{ "EPROTO", "Protocol error" },
            .{ "EPROTONOSUPPORT", "Protocol not supported" },
            .{ "EPROTOTYPE", "Protocol wrong type for socket" },
            .{ "EPWROFF", "Intelligent device errors. Device power is off" },
            .{ "EQFULL", "Interface output queue is full" },
            .{ "ERANGE", "Result too large" },
            .{ "EREMOTE", "Too many levels of remote in path" },
            .{ "EROFS", "Read-only file system" },
            .{ "ERPCMISMATCH", "RPC version wrong" },
            .{ "ESHLIBVERS", "Shared library version mismatch" },
            .{ "ESHUTDOWN", "Can't send after socket shutdown" },
            .{ "ESOCKTNOSUPPORT", "Socket type not supported" },
            .{ "ESPIPE", "Illegal seek" },
            .{ "ESRCH", "No such process" },
            .{ "ESTALE", "Network File System. Stale NFS file handle" },
            .{ "ETIME", "STREAM ioctl timeout" },
            .{ "ETIMEDOUT", "Operation timed out" },
            .{ "ETOOMANYREFS", "Too many references: can't splice" },
            .{ "ETXTBSY", "Text file busy" },
            .{ "EUSERS", "Too many users" },
            .{ "EWOULDBLOCK", "Operation would block" },
            .{ "EXDEV", "Cross-device link" },
        },
    };

    var map = std.EnumMap(SystemErrno, [:0]const u8).initFull("unknown error");
    for (entries) |entry| {
        const key, const text = entry;
        if (@hasField(SystemErrno, key)) {
            map.put(@field(SystemErrno, key), text);
        }
    }

    // sanity check
    bun.assert(std.mem.eql(u8, map.get(SystemErrno.ENOENT).?, "No such file or directory"));

    break :brk map;
};

const std = @import("std");

const bun = @import("bun");
const Environment = bun.Environment;
const SystemErrno = bun.sys.SystemErrno;
